home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / snmp / mib2c-data / mfd-interface.m2c < prev    next >
Text File  |  2008-09-22  |  52KB  |  1,717 lines

  1. #############################################################  -*- c -*-
  2. ## generic include for XXX. Do not use directly.
  3. ##
  4. ## $Id: mfd-interface.m2c 15899 2007-02-27 13:08:24Z rstory $
  5. ########################################################################
  6. @if $m2c_mark_boundary == 1@
  7. /** START code generated by $RCSfile$ $Revision: 15899 $ */
  8. @end@
  9. ########################################################################
  10. ##
  11. ########################################################################
  12. @eval $m2c_processing_type = 'h'@
  13. @open ${name}_interface.h@
  14. @eval $hack = "Id"@
  15. /*
  16.  * Note: this file originally auto-generated by mib2c using
  17.  *       version $Revision: 15899 $ of $RCSfile$
  18.  *
  19.  * $$hack:$
  20.  */
  21. /** @ingroup interface: Routines to interface to Net-SNMP
  22.  *
  23.  * \warning This code should not be modified, called directly,
  24.  *          or used to interpret functionality. It is subject to
  25.  *          change at any time.
  26.  * 
  27.  * @{
  28.  */
  29. @include m2c-internal-warning.m2i@
  30. ##
  31. @eval $m2c_save = "$name"@
  32. @eval $name = "${name}_INTERFACE"@
  33. @include generic-header-top.m2i@
  34. @eval $name = "$m2c_save"@
  35.  
  36. #include "${name}.h"
  37.  
  38.  
  39. /* ********************************************************************
  40.  * Table declarations
  41.  */
  42. @foreach $table table@
  43. @    include m2c_setup_table.m2i@
  44.  
  45. /* PUBLIC interface initialization routine */
  46. void _${context}_initialize_interface(${context}_registration * user_ctx,
  47.                                     u_long flags);
  48. void _${context}_shutdown_interface(${context}_registration * user_ctx);
  49.  
  50. ${context}_registration *
  51. ${context}_registration_get( void );
  52.  
  53. ${context}_registration *
  54. ${context}_registration_set( ${context}_registration * newreg );
  55.  
  56. netsnmp_container *${context}_container_get( void );
  57. int ${context}_container_size( void );
  58.  
  59. @   if $m2c_table_settable@
  60. u_int ${context}_dirty_get( void );
  61. void ${context}_dirty_set( u_int status );
  62.  
  63. @   end@
  64. @   if $m2c_data_allocate == 1@
  65. @      eval $m2c_tmp = "${context}_data *"@
  66. @      if $m2c_data_init == 1@
  67. @         eval $m2c_tmp = "$m2c_tmp, void *"@
  68. @      @end@
  69. @   elsif $m2c_data_init == 1@
  70. @      eval $m2c_tmp = "void *"@
  71. @   else@
  72. @      eval $m2c_tmp = "void"@
  73. @   end@
  74.     ${context}_rowreq_ctx * ${context}_allocate_rowreq_ctx($m2c_tmp);
  75. void ${context}_release_rowreq_ctx(${context}_rowreq_ctx *rowreq_ctx);
  76.  
  77. int ${context}_index_to_oid(netsnmp_index *oid_idx,
  78.                             ${context}_mib_index *mib_idx);
  79. int ${context}_index_from_oid(netsnmp_index *oid_idx,
  80.                               ${context}_mib_index *mib_idx);
  81.  
  82. @   if $m2c_table_persistent == 1@
  83. @      include mfd-persistence.m2i@
  84.  
  85. @   end@
  86. /*
  87.  * access to certain internals. use with caution!
  88.  */
  89. void ${context}_valid_columns_set(netsnmp_column_info *vc);
  90.  
  91. @end@ # for each
  92. @eval $m2c_save = "$name"@
  93. @eval $name = "${name}_INTERFACE"@
  94. @include generic-header-bottom.m2i@
  95. /** @} */
  96. @eval $name = "$m2c_save"@
  97. ########################################################################
  98. ########################################################################
  99. ########################################################################
  100. ########################################################################
  101. ########################################################################
  102. ########################################################################
  103. ########################################################################
  104. ##
  105. @open ${name}_interface.c@
  106. /*
  107.  * Note: this file originally auto-generated by mib2c using
  108.  *       version $Revision: 15899 $ of $RCSfile$ 
  109.  *
  110.  * $$hack:$
  111.  */
  112. @include m2c-internal-warning.m2i@
  113.  
  114. @include generic-source-includes.m2i@
  115.  
  116. #include <net-snmp/agent/table_container.h>
  117. #include <net-snmp/library/container.h>
  118.  
  119. #include "${name}_interface.h"
  120.  
  121. #include <ctype.h>
  122.  
  123. @eval $m2c_processing_type = 'i'@
  124. @foreach $table table@
  125. @   include m2c_setup_table.m2i@
  126. @   include details-table.m2i@
  127. ########################################################################
  128. typedef struct ${context}_interface_ctx_s {
  129.  
  130.    netsnmp_container              *container;
  131. @   if $m2c_data_cache == 1@
  132.    netsnmp_cache                  *cache;
  133. @   end@
  134.  
  135.    ${context}_registration *      user_ctx;
  136.    
  137.    netsnmp_table_registration_info  tbl_info;
  138.  
  139.    netsnmp_baby_steps_access_methods access_multiplexer;
  140.  
  141. @  if $m2c_table_settable@
  142.     u_int                             table_dirty;
  143.  
  144. @  end@
  145. } ${context}_interface_ctx;
  146.  
  147. static ${context}_interface_ctx ${context}_if_ctx;
  148.  
  149. static void _${context}_container_init(
  150.     ${context}_interface_ctx *if_ctx);
  151. static void _${context}_container_shutdown(
  152.     ${context}_interface_ctx *if_ctx);
  153.  
  154.  
  155. netsnmp_container *
  156. ${context}_container_get( void )
  157. {
  158.     return ${context}_if_ctx.container;
  159. }
  160.  
  161. ${context}_registration *
  162. ${context}_registration_get( void )
  163. {
  164.     return ${context}_if_ctx.user_ctx;
  165. }
  166.  
  167. ${context}_registration *
  168. ${context}_registration_set( ${context}_registration * newreg )
  169. {
  170.     ${context}_registration * old = ${context}_if_ctx.user_ctx;
  171.     ${context}_if_ctx.user_ctx = newreg;
  172.     return old;
  173. }
  174.  
  175. int
  176. ${context}_container_size( void )
  177. {
  178.     return CONTAINER_SIZE(${context}_if_ctx.container);
  179. }
  180.  
  181. @  if $m2c_table_settable@
  182. u_int
  183. ${context}_dirty_get( void )
  184. {
  185.     return ${context}_if_ctx.table_dirty;
  186. }
  187.  
  188. void
  189. ${context}_dirty_set( u_int status )
  190. {
  191.     DEBUGMSGTL(("${context}:${context}_dirty_set",
  192.                 "called. was %d, now %d\n",
  193.                 ${context}_if_ctx.table_dirty, status));
  194.     ${context}_if_ctx.table_dirty = status;
  195. }
  196.  
  197. @end@
  198. /*
  199.  * mfd multiplexer modes
  200.  */
  201. static Netsnmp_Node_Handler _mfd_${context}_pre_request;
  202. static Netsnmp_Node_Handler _mfd_${context}_post_request;
  203. static Netsnmp_Node_Handler _mfd_${context}_object_lookup;
  204. static Netsnmp_Node_Handler _mfd_${context}_get_values;
  205. @   if $m2c_table_settable@
  206. static Netsnmp_Node_Handler _mfd_${context}_check_objects;
  207. static Netsnmp_Node_Handler _mfd_${context}_undo_setup;
  208. static Netsnmp_Node_Handler _mfd_${context}_set_values;
  209. static Netsnmp_Node_Handler _mfd_${context}_undo_cleanup;
  210. static Netsnmp_Node_Handler _mfd_${context}_undo_values;
  211. static Netsnmp_Node_Handler _mfd_${context}_commit;
  212. static Netsnmp_Node_Handler _mfd_${context}_undo_commit;
  213. static Netsnmp_Node_Handler _mfd_${context}_irreversible_commit;
  214. @      if $m2c_table_dependencies == 1@
  215. static Netsnmp_Node_Handler _mfd_${context}_check_dependencies;
  216. @      end@
  217.  
  218. NETSNMP_STATIC_INLINE int _${context}_undo_column( ${context}_rowreq_ctx *rowreq_ctx,
  219.                                                    netsnmp_variable_list *var, int column );
  220.  
  221. @   end@ # writable
  222. @if ($m2c_table_persistent == 1) || ($m2c_table_row_creation == 1)@
  223. NETSNMP_STATIC_INLINE int _${context}_check_indexes(${context}_rowreq_ctx * rowreq_ctx);
  224.  
  225. @end@
  226. @   if ("$m2c_data_context" eq "generated") && (($m2c_undo_embed == 0) || ($m2c_data_allocate == 1))@
  227. ${context}_data *${context}_allocate_data(void);
  228.  
  229. @   end@
  230. /**
  231.  * @internal
  232.  * Initialize the table $context 
  233.  *    (Define its contents and how it's structured)
  234.  */
  235. void
  236. _${context}_initialize_interface(${context}_registration * reg_ptr,  u_long flags)
  237. {
  238.     netsnmp_baby_steps_access_methods *access_multiplexer =
  239.         &${context}_if_ctx.access_multiplexer;
  240.     netsnmp_table_registration_info *tbl_info = &${context}_if_ctx.tbl_info;
  241.     netsnmp_handler_registration *reginfo;
  242.     netsnmp_mib_handler *handler;
  243.     int    mfd_modes = 0;
  244.  
  245.     DEBUGMSGTL(("internal:${context}:_${context}_initialize_interface","called\n"));
  246.  
  247.  
  248.     /*************************************************
  249.      *
  250.      * save interface context for ${context}
  251.      */
  252.     /*
  253.      * Setting up the table's definition
  254.      */
  255.     netsnmp_table_helper_add_indexes(tbl_info,
  256.     @foreach $tabledx index@
  257.                                   $tabledx.type, /** index: $tabledx */
  258.     @end@
  259.                              0);
  260.  
  261.     /*  Define the minimum and maximum accessible columns.  This
  262.         optimizes retrival. */
  263.     tbl_info->min_column = $context.uc_MIN_COL;
  264.     tbl_info->max_column = $context.uc_MAX_COL;
  265.  
  266.     /*
  267.      * save users context
  268.      */
  269.     ${context}_if_ctx.user_ctx = reg_ptr;
  270.  
  271.     /*
  272.      * call data access initialization code
  273.      */
  274.     ${context}_init_data(reg_ptr);
  275.  
  276.     /*
  277.      * set up the container
  278.      */
  279.     _${context}_container_init(&${context}_if_ctx);
  280.     if (NULL == ${context}_if_ctx.container) {
  281.         snmp_log(LOG_ERR,"could not initialize container for ${context}\n");
  282.         return;
  283.     }
  284.     
  285.     /*
  286.      * access_multiplexer: REQUIRED wrapper for get request handling
  287.      */
  288.     access_multiplexer->object_lookup = _mfd_${context}_object_lookup;
  289.     access_multiplexer->get_values = _mfd_${context}_get_values;
  290.  
  291.     /*
  292.      * no wrappers yet
  293.      */
  294.     access_multiplexer->pre_request = _mfd_${context}_pre_request;
  295.     access_multiplexer->post_request = _mfd_${context}_post_request;
  296.  
  297. ##
  298. @   if $m2c_table_settable@
  299.  
  300.     /*
  301.      * REQUIRED wrappers for set request handling
  302.      */
  303.     access_multiplexer->object_syntax_checks = _mfd_${context}_check_objects;
  304.     access_multiplexer->undo_setup = _mfd_${context}_undo_setup;
  305.     access_multiplexer->undo_cleanup = _mfd_${context}_undo_cleanup;
  306.     access_multiplexer->set_values = _mfd_${context}_set_values;
  307.     access_multiplexer->undo_sets = _mfd_${context}_undo_values;
  308.  
  309.     /*
  310.      * no wrappers yet
  311.      */
  312.     access_multiplexer->commit = _mfd_${context}_commit;
  313.     access_multiplexer->undo_commit = _mfd_${context}_undo_commit;
  314.     access_multiplexer->irreversible_commit = _mfd_${context}_irreversible_commit;
  315. ##
  316. @      if $m2c_table_dependencies == 1@
  317.     
  318.     /*
  319.      * REQUIRED for tables with dependencies
  320.      */
  321.     access_multiplexer->consistency_checks = _mfd_${context}_check_dependencies;
  322. @      end@
  323. @   end@ # writable
  324.  
  325.     /*************************************************
  326.      *
  327.      * Create a registration, save our reg data, register table.
  328.      */
  329.     DEBUGMSGTL(("$name:init_$context",
  330.                 "Registering $context as a mibs-for-dummies table.\n"));         
  331.     handler = netsnmp_baby_steps_access_multiplexer_get(access_multiplexer);
  332.     reginfo = netsnmp_handler_registration_create("${context}", handler,
  333.                                                   ${context}_oid,
  334.                                                   ${context}_oid_size,
  335.                                                   HANDLER_CAN_BABY_STEP |
  336. @if $m2c_table_settable == 1@
  337.                                                   HANDLER_CAN_RWRITE
  338. @else@
  339.                                                   HANDLER_CAN_RONLY
  340. @end@
  341.                                                   );
  342.     if(NULL == reginfo) {
  343.         snmp_log(LOG_ERR,"error registering table ${context}\n");
  344.         return;
  345.     }
  346.     reginfo->my_reg_void = &${context}_if_ctx;
  347.  
  348.     /*************************************************
  349.      *
  350.      * set up baby steps handler, create it and inject it
  351.      */
  352.     if( access_multiplexer->object_lookup )
  353.         mfd_modes |= BABY_STEP_OBJECT_LOOKUP;
  354.     if( access_multiplexer->set_values )
  355.         mfd_modes |= BABY_STEP_SET_VALUES;
  356.     if( access_multiplexer->irreversible_commit )
  357.         mfd_modes |= BABY_STEP_IRREVERSIBLE_COMMIT;
  358.     if( access_multiplexer->object_syntax_checks )
  359.         mfd_modes |= BABY_STEP_CHECK_OBJECT;
  360.  
  361.     if( access_multiplexer->pre_request )
  362.         mfd_modes |= BABY_STEP_PRE_REQUEST;
  363.     if( access_multiplexer->post_request )
  364.         mfd_modes |= BABY_STEP_POST_REQUEST;
  365.     
  366.     if( access_multiplexer->undo_setup )
  367.         mfd_modes |= BABY_STEP_UNDO_SETUP;
  368.     if( access_multiplexer->undo_cleanup )
  369.         mfd_modes |= BABY_STEP_UNDO_CLEANUP;
  370.     if( access_multiplexer->undo_sets )
  371.         mfd_modes |= BABY_STEP_UNDO_SETS;
  372.     
  373.     if( access_multiplexer->row_creation )
  374.         mfd_modes |= BABY_STEP_ROW_CREATE;
  375.     if( access_multiplexer->consistency_checks )
  376.         mfd_modes |= BABY_STEP_CHECK_CONSISTENCY;
  377.     if( access_multiplexer->commit )
  378.         mfd_modes |= BABY_STEP_COMMIT;
  379.     if( access_multiplexer->undo_commit )
  380.         mfd_modes |= BABY_STEP_UNDO_COMMIT;
  381.     
  382.     handler = netsnmp_baby_steps_handler_get(mfd_modes);
  383.     netsnmp_inject_handler(reginfo, handler);
  384.  
  385.     /*************************************************
  386.      *
  387.      * inject row_merge helper with prefix rootoid_len + 2 (entry.col)
  388.      */
  389.     handler = netsnmp_get_row_merge_handler(reginfo->rootoid_len + 2);
  390.     netsnmp_inject_handler(reginfo, handler);
  391.  
  392.     /*************************************************
  393.      *
  394.      * inject container_table helper
  395.      */
  396.     handler =
  397.         netsnmp_container_table_handler_get(tbl_info,
  398.                                             ${context}_if_ctx.container,
  399.                                             TABLE_CONTAINER_KEY_NETSNMP_INDEX);
  400.     netsnmp_inject_handler( reginfo, handler );
  401.  
  402. @   if $m2c_data_cache == 1@
  403.     /*************************************************
  404.      *
  405.      * inject cache helper
  406.      */
  407.     if(NULL != ${context}_if_ctx.cache) {
  408.         handler = netsnmp_cache_handler_get(${context}_if_ctx.cache);
  409.         netsnmp_inject_handler( reginfo, handler );
  410.     }
  411.  
  412. @   end@
  413.     /*
  414.      * register table
  415.      */
  416.     netsnmp_register_table(reginfo, tbl_info);
  417.  
  418. @if $m2c_table_persistent == 1@
  419.     /*
  420.      * register config/persistence callbacks
  421.      */
  422.     ${context}_container_init_persistence(${context}_if_ctx.container);
  423.     
  424. @end@
  425. } /* _${context}_initialize_interface */
  426.  
  427. /**
  428.  * @internal
  429.  * Shutdown the table $context
  430.  */
  431. void
  432. _${context}_shutdown_interface(${context}_registration * reg_ptr)
  433. {
  434.     /*
  435.      * shutdown the container
  436.      */
  437.     _${context}_container_shutdown(&${context}_if_ctx);
  438. }
  439.  
  440. void
  441. ${context}_valid_columns_set(netsnmp_column_info *vc)
  442. {
  443.     ${context}_if_ctx.tbl_info.valid_columns = vc;
  444. } /* ${context}_valid_columns_set */
  445.  
  446. @include generic-table-indexes-to-oid.m2i@
  447. @include generic-table-indexes-from-oid.m2i@
  448.  
  449. ########################################################################
  450. ##
  451. @    if (($m2c_data_allocate == 1) || ($m2c_undo_embed == 0)) && ("$m2c_data_context" eq "generated")@
  452. @        eval $m2c_gda_todo_suppress = 1@ # no todo comments
  453. @        include generic-data-allocate.m2i@ # resets suppress
  454. @    end@
  455. ########################################################################
  456. /* *********************************************************************
  457.  * @internal
  458.  * allocate resources for a ${context}_rowreq_ctx
  459.  */
  460. ${context}_rowreq_ctx *
  461. @if $m2c_data_allocate == 1@
  462. @   eval $m2c_tmp = "${context}_data *data"@
  463. @   if $m2c_data_init == 1@
  464. @     eval $m2c_tmp = "$m2c_tmp, void *user_init_ctx"@
  465. @   end@
  466. @elsif $m2c_data_init == 1@
  467. @   eval $m2c_tmp = "void *user_init_ctx"@
  468. @else@
  469. @   eval $m2c_tmp = "void"@
  470. @end@
  471. ${context}_allocate_rowreq_ctx($m2c_tmp)
  472. {
  473.     ${context}_rowreq_ctx *rowreq_ctx =
  474.                   SNMP_MALLOC_TYPEDEF(${context}_rowreq_ctx);
  475.  
  476.     DEBUGMSGTL(("internal:${context}:${context}_allocate_rowreq_ctx","called\n"));
  477.  
  478.     if(NULL == rowreq_ctx) {
  479.         snmp_log(LOG_ERR,"Couldn't allocate memory for a "
  480.                  "${context}_rowreq_ctx.\n");
  481.         return NULL;
  482.     }
  483. @if $m2c_data_allocate == 1@
  484.     else {
  485.         if(NULL != data) {
  486.             /*
  487.              * track if we got data from user
  488.              */
  489.             rowreq_ctx->rowreq_flags |= MFD_ROW_DATA_FROM_USER;
  490.             rowreq_ctx->data = data;
  491.         }
  492.         else if (NULL == (rowreq_ctx->data = ${context}_allocate_data())) {
  493.             SNMP_FREE(rowreq_ctx);
  494.             return NULL;
  495.         }
  496.     }
  497.  
  498.     /*
  499.      * undo context will be allocated when needed (in *_undo_setup)
  500.      */
  501. @end@
  502.  
  503.     rowreq_ctx->oid_idx.oids = rowreq_ctx->oid_tmp;
  504.  
  505.     rowreq_ctx->${context}_data_list = NULL;
  506.  
  507. @if $m2c_data_init == 1@
  508.     /*
  509.      * if we allocated data, call init routine
  510.      */
  511.     if (!(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER)) {
  512.         if(SNMPERR_SUCCESS !=
  513.             ${context}_rowreq_ctx_init(rowreq_ctx, user_init_ctx)) {
  514.            ${context}_release_rowreq_ctx(rowreq_ctx);
  515.            rowreq_ctx = NULL;
  516.         }
  517.     }
  518. @end@
  519.  
  520.     return rowreq_ctx;
  521. } /* ${context}_allocate_rowreq_ctx */
  522.  
  523. /*
  524.  * @internal
  525.  * release resources for a ${context}_rowreq_ctx
  526.  */
  527. void
  528. ${context}_release_rowreq_ctx(${context}_rowreq_ctx *rowreq_ctx)
  529. {
  530.     DEBUGMSGTL(("internal:${context}:${context}_release_rowreq_ctx","called\n"));
  531.  
  532.     netsnmp_assert(NULL != rowreq_ctx);
  533.     
  534. @if $m2c_data_init == 1@
  535.     ${context}_rowreq_ctx_cleanup(rowreq_ctx);
  536. @end@
  537.  
  538. @if $m2c_data_allocate == 1@
  539.     /*
  540.      * for non-transient data, don't free data we got from the user
  541.      */
  542.     if ((rowreq_ctx->data) &&
  543.         !(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER))
  544.         ${context}_release_data(rowreq_ctx->data);
  545.  
  546. @end@ 
  547. @if $m2c_undo_embed == 0@
  548.     if(rowreq_ctx->undo)
  549.         ${context}_release_data(rowreq_ctx->undo);
  550.  
  551. @end@ 
  552.     /*
  553.      * free index oid pointer
  554.      */
  555.     if(rowreq_ctx->oid_idx.oids != rowreq_ctx->oid_tmp)
  556.         free(rowreq_ctx->oid_idx.oids);
  557.  
  558.     SNMP_FREE(rowreq_ctx);
  559. } /* ${context}_release_rowreq_ctx */
  560.  
  561. ########################################################################
  562. ##
  563. /**
  564.  * @internal
  565.  * wrapper
  566.  */
  567. static int
  568. _mfd_${context}_pre_request(netsnmp_mib_handler *handler,
  569.                             netsnmp_handler_registration *reginfo,
  570.                             netsnmp_agent_request_info *agtreq_info,
  571.                             netsnmp_request_info *requests)
  572. {
  573.     int rc;
  574.  
  575.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_pre_request",
  576.                 "called\n"));
  577.     
  578.     if (1 != netsnmp_row_merge_status_first(reginfo, agtreq_info)) {
  579.         DEBUGMSGTL(("internal:${context}",
  580.                     "skipping additional pre_request\n"));
  581.         return SNMP_ERR_NOERROR;
  582.     }
  583.         
  584.     rc = ${context}_pre_request(${context}_if_ctx.user_ctx);
  585.     if (MFD_SUCCESS != rc) {
  586.         /*
  587.          * nothing we can do about it but log it
  588.          */
  589.         DEBUGMSGTL(("${context}","error %d from "
  590.                     "${context}_pre_request\n", rc));
  591.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  592.     }
  593.     
  594.     return SNMP_ERR_NOERROR;
  595. } /* _mfd_${context}_pre_request */
  596.  
  597. /**
  598.  * @internal
  599.  * wrapper
  600.  */
  601. static int
  602. _mfd_${context}_post_request(netsnmp_mib_handler *handler,
  603.                              netsnmp_handler_registration *reginfo,
  604.                              netsnmp_agent_request_info *agtreq_info,
  605.                              netsnmp_request_info *requests)
  606. {
  607.     ${context}_rowreq_ctx *rowreq_ctx =
  608.                   netsnmp_container_table_row_extract(requests);
  609.     int rc, packet_rc;
  610.  
  611.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_post_request",
  612.                 "called\n"));
  613.  
  614.     /*
  615.      * release row context, if deleted
  616.      */
  617.     if (rowreq_ctx && (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED))
  618.         ${context}_release_rowreq_ctx(rowreq_ctx);
  619.  
  620.     /*
  621.      * wait for last call before calling user
  622.      */
  623.     if (1 != netsnmp_row_merge_status_last(reginfo, agtreq_info)) {
  624.         DEBUGMSGTL(("internal:${context}",
  625.                     "waiting for last post_request\n"));
  626.         return SNMP_ERR_NOERROR;
  627.     }
  628.     
  629.     packet_rc = netsnmp_check_all_requests_error(agtreq_info->asp, 0);
  630. @  if $m2c_table_settable@
  631.     if ((MFD_SUCCESS != packet_rc) && ${context}_dirty_get()) {
  632.         /*
  633.          * we shouldn't get here. the undo steps should also clear
  634.          * the dirty flags.
  635.          */
  636.         snmp_log(LOG_WARNING, "${context} dirty flag set in post_request "
  637.                  "but status != SUCCESS.\n");
  638.     }
  639.  
  640. @   end@
  641.     rc = ${context}_post_request(${context}_if_ctx.user_ctx,packet_rc);
  642.     if (MFD_SUCCESS != rc) {
  643.         /*
  644.          * nothing we can do about it but log it
  645.          */
  646.         DEBUGMSGTL(("${context}","error %d from "
  647.                     "${context}_post_request\n", rc));
  648.     }
  649.     
  650.     return SNMP_ERR_NOERROR;
  651. } /* _mfd_${context}_post_request */
  652.  
  653. ########################################################################
  654. ##
  655. @if ($m2c_table_row_creation == 1) || ($m2c_table_persistent == 1)@
  656. /**
  657.  * @internal
  658.  * wrapper
  659.  */
  660. static ${table}_rowreq_ctx *
  661. _mfd_${context}_rowreq_from_index(netsnmp_index *oid_idx, int * rc_ptr)
  662. {
  663.     ${context}_rowreq_ctx * rowreq_ctx;
  664.     ${context}_mib_index mib_idx;
  665.     int rc;
  666.  
  667.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_rowreq_from_index",
  668.                 "called\n"));
  669.  
  670.     if (NULL == rc_ptr)
  671.         rc_ptr = &rc;
  672.     *rc_ptr = MFD_SUCCESS;
  673.  
  674.     memset(&mib_idx, 0x0, sizeof(mib_idx));
  675.     
  676.     /*
  677.      * try to parse oid
  678.      */
  679.     *rc_ptr = ${context}_index_from_oid(oid_idx, &mib_idx);
  680.     if(MFD_SUCCESS != *rc_ptr) {
  681.         DEBUGMSGT(("$context", "error parsing index\n"));
  682.         return NULL;
  683.     }
  684.  
  685.     /*
  686.      * allocate new context
  687.      */
  688. @   eval $m2c_tmp = ""@
  689. @   if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
  690. @      eval $m2c_tmp = "NULL"@
  691. @      if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
  692. @         eval $m2c_tmp = "$m2c_tmp, NULL"@
  693. @      @end@
  694. @   end@
  695.     rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
  696.     if (NULL == rowreq_ctx) {
  697.         *rc_ptr = MFD_ERROR;
  698.         return NULL; /* msg already logged */
  699.     }
  700.     
  701.     memcpy(&rowreq_ctx->tbl_idx, &mib_idx, sizeof(mib_idx));
  702.  
  703.     /*
  704.      * check indexes
  705.      */
  706.     *rc_ptr = _${context}_check_indexes(rowreq_ctx);
  707.     if(MFD_SUCCESS != *rc_ptr) {
  708.         netsnmp_assert((*rc_ptr == SNMP_ERR_NOCREATION) ||
  709.                        (*rc_ptr == SNMP_ERR_INCONSISTENTNAME));
  710.         ${context}_release_rowreq_ctx(rowreq_ctx);
  711.         return NULL;
  712.     }
  713.  
  714.     /*
  715.      * copy indexes
  716.      */
  717.     rowreq_ctx->oid_idx.len = oid_idx->len;
  718.     memcpy(rowreq_ctx->oid_idx.oids, oid_idx->oids, oid_idx->len * sizeof(oid));
  719.  
  720.     return rowreq_ctx;
  721. } /* _mfd_${context}_rowreq_from_index */
  722.  
  723.  
  724. @end@ # row creation
  725. /**
  726.  * @internal
  727.  * wrapper
  728.  */
  729. static int
  730. _mfd_${context}_object_lookup(netsnmp_mib_handler *handler,
  731.                          netsnmp_handler_registration *reginfo,
  732.                          netsnmp_agent_request_info *agtreq_info,
  733.                          netsnmp_request_info *requests)
  734. {
  735.     int                    rc = SNMP_ERR_NOERROR;
  736.     ${context}_rowreq_ctx *rowreq_ctx =
  737.                   netsnmp_container_table_row_extract(requests);
  738.     
  739.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_object_lookup","called\n"));
  740.  
  741.     /*
  742.      * get our context from mfd
  743.      * ${context}_interface_ctx *if_ctx =
  744.      *             (${context}_interface_ctx *)reginfo->my_reg_void;
  745.      */
  746.  
  747.     if(NULL == rowreq_ctx) {
  748. @   if $m2c_table_row_creation == 0@
  749.         rc = SNMP_ERR_NOCREATION;
  750. @   else@
  751.         netsnmp_table_request_info *tblreq_info;
  752.         netsnmp_index oid_idx;
  753.  
  754.         tblreq_info = netsnmp_extract_table_info(requests);
  755.         if(NULL == tblreq_info) {
  756.             snmp_log(LOG_ERR, "request had no table info\n");
  757.             return MFD_ERROR;
  758.         }
  759.  
  760.         /*
  761.          * try create rowreq
  762.          */
  763.         oid_idx.oids = tblreq_info->index_oid;
  764.         oid_idx.len = tblreq_info->index_oid_len;
  765.  
  766.         rowreq_ctx = _mfd_${context}_rowreq_from_index(&oid_idx, &rc);
  767.         if(MFD_SUCCESS == rc) {
  768.             netsnmp_assert(NULL != rowreq_ctx);
  769.             rowreq_ctx->rowreq_flags |= MFD_ROW_CREATED;
  770.             /*
  771.              * add rowreq_ctx to request data lists
  772.              */
  773.             netsnmp_container_table_row_insert(requests, (netsnmp_index*)rowreq_ctx);
  774.         }
  775. @   end@ // row creation
  776.     }
  777.  
  778.     if (MFD_SUCCESS != rc)
  779.         netsnmp_request_set_error_all(requests, rc);
  780.     else
  781.         ${context}_row_prep(rowreq_ctx);
  782.  
  783.     return SNMP_VALIDATE_ERR(rc);
  784. } /* _mfd_${context}_object_lookup */
  785.  
  786. ########################################################################
  787. ##
  788. /***********************************************************************
  789.  *
  790.  * GET processing
  791.  *
  792.  ***********************************************************************/
  793. /*
  794.  * @internal
  795.  * Retrieve the value for a particular column
  796.  */
  797. NETSNMP_STATIC_INLINE int
  798. _${context}_get_column( ${context}_rowreq_ctx *rowreq_ctx,
  799.                        netsnmp_variable_list *var, int column )
  800. {
  801.     int rc = SNMPERR_SUCCESS;
  802.     
  803.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
  804.                 "called for %d\n", column));
  805.  
  806.  
  807.     netsnmp_assert(NULL != rowreq_ctx);
  808.  
  809.     switch(column) {
  810. @   foreach $node internalindex@
  811. @      include m2c_setup_node.m2i@
  812. @      if $node.accessible == 1@
  813.  
  814.     /* (INDEX) $m2c_node_summary */
  815.     case COLUMN_$node.uc:
  816.     var->type = $node.type;
  817. @         if $m2c_node_needlength == 1@
  818.     /*
  819.      * NOTE: val_len is in bytes, ${node}_len might not be (e.g. oids)
  820.      */
  821.         if (var->val_len < (rowreq_ctx->tbl_idx.${node}_len *
  822.                             sizeof(rowreq_ctx->tbl_idx.${node}[0]))) {
  823.            var->val.string = malloc(rowreq_ctx->tbl_idx.${node}_len *
  824.                                     sizeof(rowreq_ctx->tbl_idx.${node}[0]));
  825.         }
  826.         var->val_len = rowreq_ctx->tbl_idx.${node}_len * sizeof(rowreq_ctx->tbl_idx.${node}[0]);
  827.         memcpy( var->val.string, rowreq_ctx->tbl_idx.$node, var->val_len );
  828. @         else@
  829.         var->val_len = sizeof($m2c_decl);
  830.         (*var->val.integer) = rowreq_ctx->tbl_idx.$node;
  831. @         end@
  832.         break;
  833. @      end@ ## accessible
  834. @   end@ ## index
  835. @   foreach $node nonindex@
  836. @      include m2c_setup_node.m2i@
  837. @      if $node.accessible == 1@
  838.  
  839.     /* $m2c_node_summary */
  840.     case COLUMN_$node.uc:
  841. @   if $m2c_table_sparse == 1@
  842.         if (! (COLUMN_$node.uc_FLAG & rowreq_ctx->column_exists_flags)) {
  843.             DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
  844.                         "column %d ($node) doesn't exist\n", column));
  845.             return MFD_SKIP;
  846.         }
  847.  
  848. @   end@
  849. ##         use sizeof except for BITS
  850. @         if $m2c_node_needlength == 0@
  851. @            if "$node.perltype" eq "BITS"@
  852.     {
  853.         $m2c_decl mask = 0xff << ((sizeof($m2c_decl) - 1) * 8);
  854.         int       idx = 0;
  855. @            else@
  856.     var->val_len = sizeof($m2c_decl);
  857. @            end@
  858. @         end@
  859.     var->type = $node.type;
  860. rc = ${node}_get(rowreq_ctx, $m2c_node_var_ref );
  861. @         if ($m2c_node_needlength == 0) && ("$node.perltype" eq "BITS")@
  862.         /*
  863.          * check for length of bits string
  864.          */
  865.         var->val_len = 0;
  866.         while( 0 != mask ) {
  867.             ++idx;
  868.             if ( *(($m2c_decl *) var->val.string) & mask )
  869.                 var->val_len = idx;
  870.             mask = mask >> 8;
  871.         }
  872.     }
  873. @         end@
  874.         break;
  875.  @      end@ # accessible
  876. @   end@ # for each column
  877.  
  878.      default:
  879.         if ($context.uc_MIN_COL <= column && column <= $context.uc_MAX_COL) {
  880.             DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
  881.                 "assume column %d is reserved\n", column));
  882.             rc = MFD_SKIP;
  883.         } else {
  884.             snmp_log(LOG_ERR,
  885.                 "unknown column %d in _${context}_get_column\n", column);
  886.         }
  887.         break;
  888.     }
  889.  
  890.     return rc;
  891. } /* _${context}_get_column */
  892.  
  893. ########################################################################
  894. ##
  895. int
  896. _mfd_${context}_get_values(netsnmp_mib_handler *handler,
  897.                          netsnmp_handler_registration *reginfo,
  898.                          netsnmp_agent_request_info *agtreq_info,
  899.                          netsnmp_request_info *requests)
  900. {
  901.     ${context}_rowreq_ctx *rowreq_ctx =
  902.                   netsnmp_container_table_row_extract(requests);
  903.     netsnmp_table_request_info * tri;
  904.     u_char                     * old_string;
  905.     void                      (*dataFreeHook)(void *);
  906.     int                        rc;
  907.  
  908.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_values","called\n"));
  909.  
  910.     netsnmp_assert(NULL != rowreq_ctx);
  911.     
  912. @if $m2c_table_sparse == 1@
  913.     DEBUGMSGTL(("9:${context}:_mfd_${context}_get_values",
  914.                 "exists %p\n", (void*)rowreq_ctx->column_exists_flags));
  915.  
  916. @end@
  917.     for(;requests; requests = requests->next) {
  918.         /*
  919.          * save old pointer, so we can free it if replaced
  920.          */
  921.         old_string = requests->requestvb->val.string;
  922.         dataFreeHook = requests->requestvb->dataFreeHook;
  923.         if(NULL == requests->requestvb->val.string) {
  924.             requests->requestvb->val.string = requests->requestvb->buf;
  925.             requests->requestvb->val_len = sizeof(requests->requestvb->buf);
  926.         }
  927.         else if(requests->requestvb->buf == requests->requestvb->val.string) {
  928.             if(requests->requestvb->val_len != sizeof(requests->requestvb->buf))
  929.                 requests->requestvb->val_len = sizeof(requests->requestvb->buf);
  930.         }
  931.  
  932.         /*
  933.          * get column data
  934.          */
  935.         tri = netsnmp_extract_table_info(requests);
  936.         if(NULL == tri)
  937.             continue;
  938.         
  939.         rc = _${context}_get_column(rowreq_ctx, requests->requestvb, tri->colnum);
  940.         if(rc) {
  941.             if(MFD_SKIP == rc) {
  942.                 requests->requestvb->type = SNMP_NOSUCHINSTANCE;
  943.                 rc = SNMP_ERR_NOERROR;
  944.             }
  945.         }
  946.         else if (NULL == requests->requestvb->val.string) {
  947.             snmp_log(LOG_ERR,"NULL varbind data pointer!\n");
  948.             rc = SNMP_ERR_GENERR;
  949.         }
  950.         if(rc)
  951.             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
  952.  
  953.         /*
  954.          * if the buffer wasn't used previously for the old data (i.e. it
  955.          * was allcoated memory)  and the get routine replaced the pointer,
  956.          * we need to free the previous pointer.
  957.          */
  958.         if(old_string && (old_string != requests->requestvb->buf) &&
  959.            (requests->requestvb->val.string != old_string)) {
  960.             if(dataFreeHook)
  961.                 (*dataFreeHook)(old_string);
  962.             else
  963.                 free(old_string);
  964.         }
  965.     } /* for results */
  966.  
  967.     return SNMP_ERR_NOERROR;
  968. } /* _mfd_${context}_get_values */
  969.  
  970. ##----------------------------------------------------------------------
  971. @if ($m2c_table_row_creation == 1) || ($m2c_table_persistent == 1)@
  972. NETSNMP_STATIC_INLINE int
  973. _${context}_check_indexes(${context}_rowreq_ctx * rowreq_ctx)
  974. {
  975.     int                          rc = SNMPERR_SUCCESS;
  976.  
  977.     DEBUGMSGTL(("internal:${context}:_${context}_check_indexes","called\n"));
  978.  
  979.     netsnmp_assert(NULL != rowreq_ctx);
  980.  
  981. ##
  982. @if $m2c_table_external_indexes != 0@
  983.     /*
  984.      * check that the corresponding EXTERNAL row exists
  985.      */
  986. @   foreach $node externalindex@
  987. @      include m2c_setup_node.m2i@
  988.  
  989.     /* (INDEX) $m2c_node_summary */
  990.     rc = ${context}_${node}_check_index( rowreq_ctx );
  991.     if(MFD_SUCCESS != rc)
  992.         return SNMP_ERR_NOCREATION;
  993. @   end@ # for each nonindex
  994.  
  995. @end@ # external index
  996. @   foreach $node internalindex@
  997. @      include m2c_setup_node.m2i@
  998.  
  999.     /* (INDEX) $m2c_node_summary */
  1000. @   eval $m2c_nv_val = "rowreq_ctx->tbl_idx.$node"@
  1001. @   eval $m2c_nv_len = "rowreq_ctx->tbl_idx.${node}_len"@
  1002. @   eval $m2c_nv_str = "rowreq_ctx->tbl_idx.$node"@
  1003. @   include node-validate.m2i@
  1004.        if (MFD_SUCCESS != rc)
  1005.           return rc;
  1006.         rc = ${node}_check_index( rowreq_ctx );
  1007.        if(MFD_SUCCESS != rc)
  1008.            return SNMP_ERR_NOCREATION;
  1009. @   end@ # for each internalindex
  1010.  
  1011.     /*
  1012.      * if individual parts look ok, check them as a whole
  1013.      */
  1014.     return ${context}_validate_index( ${context}_if_ctx.user_ctx, rowreq_ctx );
  1015. } /* _${context}_check_indexes */
  1016. @end@ # $m2c_table_row_creation
  1017.  
  1018. ########################################################################
  1019. ##
  1020. /***********************************************************************
  1021.  *
  1022.  * SET processing
  1023.  *
  1024.  ***********************************************************************/
  1025.  
  1026. @if $m2c_table_settable == 0@
  1027. /*
  1028.  * SET PROCESSING NOT APPLICABLE (per MIB or user setting)
  1029.  */
  1030. @else@
  1031. /*----------------------------------------------------------------------
  1032.  *
  1033.  * SET: Syntax checks
  1034.  *
  1035.  *---------------------------------------------------------------------*/
  1036. /*
  1037.  * @internal
  1038.  * Check the syntax for a particular column
  1039.  */
  1040. NETSNMP_STATIC_INLINE int
  1041. _${context}_check_column( ${context}_rowreq_ctx *rowreq_ctx,
  1042.                          netsnmp_variable_list *var, int column )
  1043. {
  1044.     int rc = SNMPERR_SUCCESS;
  1045.     
  1046.     DEBUGMSGTL(("internal:${context}:_${context}_check_column",
  1047.                 "called for %d\n", column));
  1048.  
  1049.     netsnmp_assert(NULL != rowreq_ctx);
  1050.  
  1051.     switch(column) {
  1052. @   eval $m2c_nvv_item = "${m2c_context_item}tbl_idx."@
  1053. @   foreach $node internalindex@
  1054. @      include m2c_setup_node.m2i@
  1055.     /* (INDEX) $m2c_node_summary */
  1056.     case COLUMN_$node.uc:
  1057.         rc = SNMP_ERR_NOTWRITABLE; /* can not change index of active row */
  1058.         break;
  1059. @   end@ ## index
  1060. @   eval $m2c_nvv_item = "$m2c_data_item"@
  1061. @   foreach $node nonindex@
  1062. @      include m2c_setup_node.m2i@
  1063. @      if $node.settable == 0@
  1064.  
  1065.     /* $m2c_node_summary */
  1066.     case COLUMN_$node.uc:
  1067.         rc = SNMP_ERR_NOTWRITABLE;
  1068.         break;
  1069. @          next@
  1070. @      end@
  1071.  
  1072.     /* $m2c_node_summary */
  1073.     case COLUMN_$node.uc:
  1074. @      include node-varbind-validate.m2i@
  1075.     if(SNMPERR_SUCCESS != rc) {
  1076.         DEBUGMSGTL(("${context}:_${context}_check_column:$node",
  1077.                     "varbind validation failed (eg bad type or size)\n"));
  1078.     }
  1079.     else {
  1080.         rc = ${node}_check_value( rowreq_ctx, $m2c_node_var_val );
  1081.         if((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc) &&
  1082.            (MFD_NOT_VALID_NOW != rc)) {
  1083.             snmp_log(LOG_ERR, "bad rc %d from ${node}_check_value\n", rc);
  1084.             rc = SNMP_ERR_GENERR;
  1085.         }
  1086.     }
  1087.         break;
  1088. @   end@ # for each nonindex
  1089.  
  1090.         default: /** We shouldn't get here */
  1091.             rc = SNMP_ERR_GENERR;
  1092.             snmp_log(LOG_ERR, "unknown column %d in _${context}_check_column\n", column);
  1093.     }
  1094.  
  1095.     return rc;
  1096. } /* _${context}_check_column */
  1097.  
  1098. ##----------------------------------------------------------------------
  1099. int
  1100. _mfd_${context}_check_objects(netsnmp_mib_handler *handler,
  1101.                          netsnmp_handler_registration *reginfo,
  1102.                          netsnmp_agent_request_info *agtreq_info,
  1103.                          netsnmp_request_info *requests)
  1104. {
  1105.     ${context}_rowreq_ctx *rowreq_ctx =
  1106.                   netsnmp_container_table_row_extract(requests);
  1107.     netsnmp_table_request_info * tri;
  1108.     int                          rc;
  1109.  
  1110.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_check_objects","called\n"));
  1111.  
  1112.     netsnmp_assert(NULL != rowreq_ctx);
  1113.     
  1114.     for(;requests; requests = requests->next) {
  1115.  
  1116.         /*
  1117.          * get column number from table request info, and check that column
  1118.          */
  1119.         tri = netsnmp_extract_table_info(requests);
  1120.         if(NULL == tri)
  1121.             continue;
  1122.  
  1123.         rc = _${context}_check_column(rowreq_ctx, requests->requestvb, tri->colnum);
  1124.         if(rc) {
  1125.             netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
  1126.             break;
  1127.         }
  1128.  
  1129.     } /* for results */
  1130.  
  1131.     return SNMP_ERR_NOERROR;
  1132. } /* _mfd_${context}_check_objects */
  1133.  
  1134.  
  1135. @      if $m2c_table_dependencies == 1@
  1136. /*----------------------------------------------------------------------
  1137.  *
  1138.  * SET: check dependencies
  1139.  *
  1140.  *---------------------------------------------------------------------*/
  1141. /*
  1142.  * @internal
  1143.  * Check dependencies wrapper
  1144.  */
  1145. static int
  1146. _mfd_${context}_check_dependencies(netsnmp_mib_handler *handler,
  1147.                          netsnmp_handler_registration *reginfo,
  1148.                          netsnmp_agent_request_info *agtreq_info,
  1149.                          netsnmp_request_info *requests)
  1150. {
  1151.     int                    rc;
  1152.     ${context}_rowreq_ctx *rowreq_ctx =
  1153.                   netsnmp_container_table_row_extract(requests);
  1154.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_check_dependencies","called\n"));
  1155.  
  1156.     netsnmp_assert(NULL != rowreq_ctx);
  1157.  
  1158.     rc = ${context}_check_dependencies(rowreq_ctx);
  1159.     if(rc){
  1160.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1161.                     "${context}_check_dependencies\n", rc));
  1162.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  1163.     }
  1164.  
  1165.     return SNMP_ERR_NOERROR;
  1166. } /* _mfd_${context}_check_dependencies */
  1167.  
  1168. @end@ // dependencies
  1169. /*----------------------------------------------------------------------
  1170.  *
  1171.  * SET: Undo setup
  1172.  *
  1173.  *---------------------------------------------------------------------*/
  1174. /*
  1175.  * @internal
  1176.  * Set the value for a particular column
  1177.  */
  1178. NETSNMP_STATIC_INLINE int
  1179. _${context}_undo_setup_column( ${context}_rowreq_ctx *rowreq_ctx, int column )
  1180. {
  1181.     int rc = SNMPERR_SUCCESS;
  1182.     
  1183.     DEBUGMSGTL(("internal:${context}:_${context}_undo_setup_column",
  1184.                 "called for %d\n", column));
  1185.  
  1186.     netsnmp_assert(NULL != rowreq_ctx);
  1187.  
  1188.     switch(column) {
  1189. @   foreach $node nonindex@
  1190. @      include m2c_setup_node.m2i@
  1191. @      if $node.settable == 1@
  1192.  
  1193.     /* $m2c_node_summary */
  1194.     case COLUMN_$node.uc:
  1195.         rowreq_ctx->column_set_flags |= COLUMN_$node.uc_FLAG;
  1196.         rc = ${node}_undo_setup(rowreq_ctx );
  1197.         break;
  1198.  @      end@ # settable
  1199. @   end@ # for each column
  1200.  
  1201.      default:
  1202.          snmp_log(LOG_ERR,"unknown column %d in _${context}_undo_setup_column\n", column);
  1203.          break;
  1204.     }
  1205.  
  1206.     return rc;
  1207. } /* _${context}_undo_setup_column */
  1208.  
  1209.  
  1210. ##----------------------------------------------------------------------
  1211. /**
  1212.  * @internal
  1213.  * undo setup
  1214.  */
  1215. int
  1216. _mfd_${context}_undo_setup(netsnmp_mib_handler *handler,
  1217.                          netsnmp_handler_registration *reginfo,
  1218.                          netsnmp_agent_request_info *agtreq_info,
  1219.                          netsnmp_request_info *requests)
  1220. {
  1221.     int                    rc;
  1222.     ${context}_rowreq_ctx *rowreq_ctx =
  1223.                   netsnmp_container_table_row_extract(requests);
  1224.  
  1225.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_setup","called\n"));
  1226.  
  1227.     netsnmp_assert(NULL != rowreq_ctx);
  1228.  
  1229. @if $m2c_undo_embed == 0@
  1230.     /*
  1231.      * allocate undo context
  1232.      */
  1233.     rowreq_ctx->undo = ${context}_allocate_data();
  1234.     if(NULL == rowreq_ctx->undo) {
  1235.         /** msg already logged */
  1236.         netsnmp_request_set_error_all(requests, SNMP_ERR_RESOURCEUNAVAILABLE);
  1237.         return SNMP_ERR_NOERROR;
  1238.     }
  1239.  
  1240. @end@
  1241.     /*
  1242.      * row undo setup
  1243.      */
  1244.     rowreq_ctx->column_set_flags = 0;
  1245.     rc = ${context}_undo_setup(rowreq_ctx);
  1246.     if (MFD_SUCCESS != rc)  {
  1247.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1248.                     "${context}_undo_setup\n", rc));
  1249.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  1250.     }
  1251.     else {
  1252.         /*
  1253.          * column undo setup
  1254.          */
  1255.         netsnmp_table_request_info * tri;
  1256.         for(;requests; requests = requests->next) {
  1257.             /*
  1258.              * set column data
  1259.              */
  1260.             tri = netsnmp_extract_table_info(requests);
  1261.             if(NULL == tri)
  1262.                 continue;
  1263.             
  1264.             rc = _${context}_undo_setup_column(rowreq_ctx, tri->colnum);
  1265.             if(MFD_SUCCESS != rc)  {
  1266.                 DEBUGMSGTL(("${context}:mfd","error %d from "
  1267.                             "${context}_undo_setup_column\n", rc));
  1268.                 netsnmp_set_request_error(agtreq_info, requests, SNMP_VALIDATE_ERR(rc));
  1269.             }
  1270.         } /* for results */
  1271.     }
  1272.     
  1273.     return SNMP_ERR_NOERROR;
  1274. } /* _mfd_${context}_undo_setup */
  1275.  
  1276. /**
  1277.  * @internal
  1278.  * undo setup
  1279.  */
  1280. int
  1281. _mfd_${context}_undo_cleanup(netsnmp_mib_handler *handler,
  1282.                              netsnmp_handler_registration *reginfo,
  1283.                              netsnmp_agent_request_info *agtreq_info,
  1284.                              netsnmp_request_info *requests)
  1285. {
  1286.     ${context}_rowreq_ctx *rowreq_ctx =
  1287.                   netsnmp_container_table_row_extract(requests);
  1288.     int rc;
  1289.  
  1290.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_cleanup","called\n"));
  1291.  
  1292.     /*
  1293.      * failed row create in early stages has no rowreq_ctx
  1294.      */
  1295.     if (NULL == rowreq_ctx)
  1296.         return MFD_SUCCESS;
  1297.  
  1298.     /*
  1299.      * call user cleanup
  1300.      */
  1301.     rc = ${context}_undo_cleanup(rowreq_ctx);
  1302.     if (MFD_SUCCESS != rc) {
  1303.         /*
  1304.          * nothing we can do about it but log it
  1305.          */
  1306.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1307.                     "${context}_undo_cleanup\n", rc));
  1308.     }
  1309.  
  1310. @if $m2c_undo_embed == 0@
  1311.     /*
  1312.      * release undo context, if needed
  1313.      */
  1314.     if(rowreq_ctx->undo) {
  1315.          ${context}_release_data(rowreq_ctx->undo);
  1316.          rowreq_ctx->undo = NULL;
  1317.     }
  1318.  
  1319. @end@
  1320.  
  1321.     return SNMP_ERR_NOERROR;
  1322. } /* _mfd_${context}_undo_cleanup */
  1323.  
  1324. /*----------------------------------------------------------------------
  1325.  *
  1326.  * SET: Set values
  1327.  *
  1328.  *---------------------------------------------------------------------*/
  1329. /*
  1330.  * @internal
  1331.  * Set the value for a particular column
  1332.  */
  1333. NETSNMP_STATIC_INLINE int
  1334. _${context}_set_column( ${context}_rowreq_ctx *rowreq_ctx,
  1335.                        netsnmp_variable_list *var, int column )
  1336. {
  1337.     int rc = SNMPERR_SUCCESS;
  1338.     
  1339.     DEBUGMSGTL(("internal:${context}:_${context}_set_column",
  1340.                 "called for %d\n", column));
  1341.  
  1342.     netsnmp_assert(NULL != rowreq_ctx);
  1343.  
  1344.     switch(column) {
  1345. @   foreach $node nonindex@
  1346. @      include m2c_setup_node.m2i@
  1347. @      if $node.settable == 1@
  1348.  
  1349.     /* $m2c_node_summary */
  1350.     case COLUMN_$node.uc:
  1351.         rowreq_ctx->column_set_flags |= COLUMN_$node.uc_FLAG;
  1352.         rc = ${node}_set(rowreq_ctx, $m2c_node_var_val );
  1353.         break;
  1354.  @      end@ # settable
  1355. @   end@ # for each column
  1356.  
  1357.      default:
  1358.          snmp_log(LOG_ERR,"unknown column %d in _${context}_set_column\n", column);
  1359.          rc = SNMP_ERR_GENERR;
  1360.          break;
  1361.     }
  1362.     
  1363.     return rc;
  1364. } /* _${context}_set_column */
  1365.  
  1366. ########################################################################
  1367. ##
  1368. int
  1369. _mfd_${context}_set_values(netsnmp_mib_handler *handler,
  1370.                          netsnmp_handler_registration *reginfo,
  1371.                          netsnmp_agent_request_info *agtreq_info,
  1372.                          netsnmp_request_info *requests)
  1373. {
  1374.     ${context}_rowreq_ctx *rowreq_ctx =
  1375.                   netsnmp_container_table_row_extract(requests);
  1376.     netsnmp_table_request_info * tri;
  1377.     int                          rc = SNMP_ERR_NOERROR;
  1378.  
  1379.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_set_values","called\n"));
  1380.  
  1381.     netsnmp_assert(NULL != rowreq_ctx);
  1382.     
  1383.     rowreq_ctx->column_set_flags = 0;
  1384.     for(;requests; requests = requests->next) {
  1385.         /*
  1386.          * set column data
  1387.          */
  1388.         tri = netsnmp_extract_table_info(requests);
  1389.         if(NULL == tri)
  1390.             continue;
  1391.         
  1392.         rc = _${context}_set_column(rowreq_ctx,
  1393.                                     requests->requestvb, tri->colnum);
  1394.         if(MFD_SUCCESS != rc)  {
  1395.             DEBUGMSGTL(("${context}:mfd","error %d from "
  1396.                         "${context}_set_column\n", rc));
  1397.             netsnmp_set_request_error(agtreq_info, requests, SNMP_VALIDATE_ERR(rc));
  1398.         }
  1399.     } /* for results */
  1400.  
  1401.     return SNMP_ERR_NOERROR;
  1402. } /* _mfd_${context}_set_values */
  1403.  
  1404. /*----------------------------------------------------------------------
  1405.  *
  1406.  * SET: commit
  1407.  *
  1408.  *---------------------------------------------------------------------*/
  1409. /**
  1410.  * @internal
  1411.  * commit the values
  1412.  */
  1413. int
  1414. _mfd_${context}_commit(netsnmp_mib_handler *handler,
  1415.                          netsnmp_handler_registration *reginfo,
  1416.                          netsnmp_agent_request_info *agtreq_info,
  1417.                          netsnmp_request_info *requests)
  1418. {
  1419.     int                    rc;
  1420.     ${context}_rowreq_ctx *rowreq_ctx =
  1421.                   netsnmp_container_table_row_extract(requests);
  1422.  
  1423.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_commit","called\n"));
  1424.  
  1425.     netsnmp_assert(NULL != rowreq_ctx);
  1426.     
  1427.     rc = ${context}_commit(rowreq_ctx);
  1428.     if (MFD_SUCCESS != rc) {
  1429.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1430.                     "${context}_commit\n", rc));
  1431.         netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
  1432.     }
  1433.  
  1434.     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
  1435.         /*
  1436.          * if we successfully commited this row, set the dirty flag. Use the
  1437.          * current value + 1 (i.e. dirty = # rows changed).
  1438.          * this is checked in post_request...
  1439.          */
  1440.         ${context}_dirty_set( ${context}_dirty_get() + 1 ); /* set table dirty flag */
  1441.     }
  1442.  
  1443.     return SNMP_ERR_NOERROR;
  1444. }
  1445.  
  1446. int
  1447. _mfd_${context}_undo_commit(netsnmp_mib_handler *handler,
  1448.                          netsnmp_handler_registration *reginfo,
  1449.                          netsnmp_agent_request_info *agtreq_info,
  1450.                          netsnmp_request_info *requests)
  1451. {
  1452.     int                    rc;
  1453.     ${context}_rowreq_ctx *rowreq_ctx =
  1454.                   netsnmp_container_table_row_extract(requests);
  1455.  
  1456.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_commit","called\n"));
  1457.  
  1458.     netsnmp_assert(NULL != rowreq_ctx);
  1459.  
  1460.     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
  1461.         u_int  d = ${context}_dirty_get();
  1462.  
  1463.         netsnmp_assert(d != 0);
  1464.         if(d)
  1465.             ${context}_dirty_set( d - 1 );
  1466.     }
  1467.  
  1468.     rc = ${context}_undo_commit(rowreq_ctx);
  1469.     if (MFD_SUCCESS != rc) {
  1470.         /*
  1471.          * nothing we can do about it but log it
  1472.          */
  1473.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1474.                     "${context}_undo_commit\n", rc));
  1475.     }
  1476.  
  1477.     if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
  1478.         snmp_log(LOG_WARNING, "${context} row dirty flag still set after undo_commit\n");
  1479.         rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
  1480.     }
  1481.  
  1482.     return SNMP_ERR_NOERROR;
  1483. } /* _mfd_${context}_commit */
  1484.  
  1485. /*----------------------------------------------------------------------
  1486.  *
  1487.  * SET: Undo
  1488.  *
  1489.  *---------------------------------------------------------------------*/
  1490. /**
  1491.  * @internal
  1492.  * undo the value for a particular column
  1493.  */
  1494. NETSNMP_STATIC_INLINE int
  1495. _${context}_undo_column( ${context}_rowreq_ctx *rowreq_ctx,
  1496.                        netsnmp_variable_list *var, int column )
  1497. {
  1498.     int rc = SNMPERR_SUCCESS;
  1499.     
  1500.     DEBUGMSGTL(("internal:${context}:_${context}_undo_column",
  1501.                 "called for %d\n", column));
  1502.  
  1503.     netsnmp_assert(NULL != rowreq_ctx);
  1504.  
  1505.     switch(column) {
  1506. @   foreach $node nonindex@
  1507. @      include m2c_setup_node.m2i@
  1508. @      if $node.settable == 1@
  1509.  
  1510.     /* $m2c_node_summary */
  1511.     case COLUMN_$node.uc:
  1512.         rc = ${node}_undo(rowreq_ctx);
  1513.         break;
  1514.  @      end@ # settable
  1515. @   end@ # for each column
  1516.  
  1517.      default:
  1518.          snmp_log(LOG_ERR,"unknown column %d in _${context}_undo_column\n", column);
  1519.          break;
  1520.     }
  1521.  
  1522.     return rc;
  1523. } /* _${context}_undo_column */
  1524.  
  1525. ########################################################################
  1526. ##
  1527. int
  1528. _mfd_${context}_undo_values(netsnmp_mib_handler *handler,
  1529.                          netsnmp_handler_registration *reginfo,
  1530.                          netsnmp_agent_request_info *agtreq_info,
  1531.                          netsnmp_request_info *requests)
  1532. {
  1533.     int                    rc;
  1534.     ${context}_rowreq_ctx *rowreq_ctx =
  1535.                   netsnmp_container_table_row_extract(requests);
  1536.     netsnmp_table_request_info * tri;
  1537.  
  1538.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_values","called\n"));
  1539.  
  1540.     netsnmp_assert(NULL != rowreq_ctx);
  1541.     
  1542.     rc = ${context}_undo(rowreq_ctx);
  1543.     if (MFD_SUCCESS != rc) {
  1544.         /*
  1545.          * nothing we can do about it but log it
  1546.          */
  1547.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1548.                     "${context}_undo\n", rc));
  1549.     }
  1550.     
  1551.     for(;requests; requests = requests->next) {
  1552.         /*
  1553.          * set column data
  1554.          */
  1555.         tri = netsnmp_extract_table_info(requests);
  1556.         if(NULL == tri)
  1557.             continue;
  1558.         
  1559.         rc = _${context}_undo_column(rowreq_ctx, requests->requestvb,
  1560.                                      tri->colnum);
  1561.         if (MFD_SUCCESS != rc) {
  1562.             /*
  1563.              * nothing we can do about it but log it
  1564.              */
  1565.             DEBUGMSGTL(("${context}:mfd","error %d from "
  1566.                         "${context}_undo_column\n", rc));
  1567.         }
  1568.     } /* for results */
  1569.  
  1570.     return SNMP_ERR_NOERROR;
  1571. } /* _mfd_${context}_undo_values */
  1572.  
  1573. /*----------------------------------------------------------------------
  1574.  *
  1575.  * SET: irreversible commit
  1576.  *
  1577.  *---------------------------------------------------------------------*/
  1578. /**
  1579.  * @internal
  1580.  * commit irreversible actions
  1581.  */
  1582. int
  1583. _mfd_${context}_irreversible_commit(netsnmp_mib_handler *handler,
  1584.                          netsnmp_handler_registration *reginfo,
  1585.                          netsnmp_agent_request_info *agtreq_info,
  1586.                          netsnmp_request_info *requests)
  1587. {
  1588. @   if $m2c_irreversible_commit == 1@
  1589.     int                    rc;
  1590. @   end@
  1591.     ${context}_rowreq_ctx *rowreq_ctx =
  1592.                   netsnmp_container_table_row_extract(requests);
  1593.     
  1594.     DEBUGMSGTL(("internal:${context}:_mfd_${context}_irreversible:commit","called\n"));
  1595.    
  1596.     netsnmp_assert(NULL != rowreq_ctx);
  1597.     
  1598. @   if $m2c_irreversible_commit == 1@
  1599.     rc = ${context}_irreversible_commit(rowreq_ctx);
  1600.     if (MFD_SUCCESS != rc) {
  1601.         netsnmp_request_set_error_all(requests, SNMP_ERR_COMMITFAILED);
  1602.         DEBUGMSGTL(("${context}:mfd","error %d from "
  1603.                     "${context}_irreversible_commit\n", rc));
  1604.     }
  1605.  
  1606. @   end@
  1607.     /*
  1608.      * check for and handle row creation/deletion
  1609.      * and update column exist flags...
  1610.      */
  1611.     if (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED) {
  1612.         if (! (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED))
  1613.             CONTAINER_REMOVE(${context}_if_ctx.container, rowreq_ctx);
  1614.     }
  1615.     else {
  1616.         if (rowreq_ctx->column_set_flags) {
  1617. @if $m2c_table_sparse == 1@
  1618.            DEBUGMSGTL(("internal:${context}:_mfd_irreversible_commit",
  1619.                        "updating exists (%p) w/set (%p) = %p\n",
  1620.                        rowreq_ctx->column_exists_flags,
  1621.                        rowreq_ctx->column_set_flags,
  1622.                        (rowreq_ctx->column_exists_flags |
  1623.                         rowreq_ctx->column_set_flags)));
  1624.            rowreq_ctx->column_exists_flags |=
  1625.            rowreq_ctx->column_set_flags;
  1626. @end@ # sparse
  1627.            rowreq_ctx->column_set_flags = 0;
  1628.         }
  1629. @if ($m2c_table_row_creation == 1)@
  1630.         if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
  1631.             rowreq_ctx->rowreq_flags &= ~MFD_ROW_CREATED;
  1632.             CONTAINER_INSERT(${context}_if_ctx.container, rowreq_ctx);
  1633.         }
  1634. @end@ # creation
  1635.     }
  1636.  
  1637.     return SNMP_ERR_NOERROR;
  1638. } /* _mfd_${context}_irreversible_commit */
  1639.  
  1640. @end@ # settable
  1641. /***********************************************************************
  1642.  *
  1643.  * DATA ACCESS
  1644.  *
  1645.  ***********************************************************************/
  1646. @    include mfd-access-${m2c_table_access}-defines.m2i@
  1647. @    if $m2c_table_persistent == 1@
  1648. @       include mfd-persistence.m2i@
  1649. @    end@
  1650.  
  1651. ${context}_rowreq_ctx *
  1652. ${context}_row_find_by_mib_index(${context}_mib_index *mib_idx)
  1653. {
  1654.     ${context}_rowreq_ctx   *rowreq_ctx;
  1655.     oid                      oid_tmp[MAX_OID_LEN];
  1656.     netsnmp_index            oid_idx;
  1657.     int                      rc;
  1658.  
  1659.     /*
  1660.      * set up storage for OID
  1661.      */
  1662.     oid_idx.oids = oid_tmp;
  1663.     oid_idx.len = sizeof(oid_tmp)/sizeof(oid);
  1664.  
  1665.     /*
  1666.      * convert
  1667.      */
  1668.     rc = ${context}_index_to_oid(&oid_idx, mib_idx);
  1669.     if (MFD_SUCCESS != rc)
  1670.         return NULL;
  1671.  
  1672.     rowreq_ctx = CONTAINER_FIND(${context}_if_ctx.container, &oid_idx);
  1673.  
  1674.     return rowreq_ctx;
  1675. }
  1676.  
  1677. @   if $m2c_table_refcounts == 1@
  1678. int
  1679. ${context}_row_ref_increment(${context}_rowreq_ctx *rowreq_ctx)
  1680. {
  1681.     if (NULL == rowreq_ctx)
  1682.         return -1;
  1683.     
  1684.     ++rowreq_ctx->ref_count;
  1685.     DEBUGMSGTL(("${context}:${context}_row_ref_increment",
  1686.                 "row %p ref count is %d\n",rowreq_ctx,
  1687.                 rowreq_ctx->ref_count));
  1688.  
  1689.     return MFD_SUCCESS;
  1690. }
  1691.  
  1692. int
  1693. ${context}_row_ref_decrement(${context}_rowreq_ctx *rowreq_ctx)
  1694. {
  1695.     if (NULL == rowreq_ctx)
  1696.         return -1;
  1697.     
  1698.     if (0 == rowreq_ctx->ref_count) {
  1699.         snmp_log(LOG_WARNING,"attempt to decrement ref_count below 0\n");
  1700.         return -2;
  1701.     }
  1702.     --rowreq_ctx->ref_count;
  1703.     DEBUGMSGTL(("${context}:${context}_row_ref_decrement",
  1704.                 "row %p ref count is %d\n",rowreq_ctx,
  1705.                 rowreq_ctx->ref_count));
  1706.  
  1707.     return MFD_SUCCESS;
  1708. }
  1709.     
  1710. @   end@ // refcounts
  1711. @end@ # foreach table
  1712. ##
  1713. ########################################################################
  1714. @if $m2c_mark_boundary == 1@
  1715. /** END code generated by $RCSfile$ $Revision: 15899 $ */
  1716. @end@
  1717.